import { css } from "@emotion/react"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import Svg from "@/components/base/Svg"
import { useModalSlideUp } from "@/features/useModal"
import styled from "@emotion/styled"
import { createLogger } from "@/utils/logger"
import { getCurrentPx } from "@/utils/common"
import { hideScrollbarCss } from "@/styles/variables/css"

const logger = createLogger("BaseSelection ModalSelection")

type Option<out V> = {
    value: V
    label: string
}

type Props<V> = {
    options: Option<V>[]
    onChange: (value: V) => void
    value?: V
    defaultValue?: V
    disabled?: boolean
    status?: "idle" | "focus" | "error" | "valid" | "disabled"
    placeholder?: string
    label?: string
}

export default function BaseSelection<V>(props: Props<V>) {
    const {
        //
        value: _value,
        options: _options,
        onChange,
        defaultValue: _defaultValue,
        disabled,
        status: _status,
        placeholder: _placeholder,
        label: _label,
    } = props

    const selectionId = useRef(`selection-${Math.random().toString(36).substring(2, 9)}`).current
    const {
        openWithId: openModal,
        close: closeModal,
        state: modalState,
    } = useModalSlideUp("kyc-page")
    const initialValue = useRef(_value)

    const [status, setStatus] = useState<NonNullable<typeof _status>>(_status ?? "idle")

    const finalValue = useMemo(() => {
        return _value ?? _defaultValue ?? ""
    }, [_value, _defaultValue])

    const existOption = useMemo(() => {
        return _options.find((option) => option.value === initialValue.current)
    }, [_options])

    const defaultOption = useMemo(() => {
        return {
            label: existOption ? _placeholder || "Select" : initialValue.current || _placeholder,
            value: existOption ? "" : initialValue.current || "",
        }
    }, [existOption, _placeholder])

    const finalOptions = useMemo(() => {
        return [defaultOption, ..._options].filter(Boolean)
    }, [_options, defaultOption])

    const finalDisplayValue = useMemo(() => {
        const option = finalOptions.find((option) => option.value === finalValue)
        return option?.label ?? ""
    }, [finalOptions, finalValue])

    const finalStatus = useMemo(() => {
        if (disabled) {
            return "disabled"
        }
        return _status ?? status
    }, [disabled, _status, status])

    const BoxShadowColor = useMemo(() => {
        switch (finalStatus) {
            case "valid":
                return "#008000"
            case "error":
                return "#FF0000"
            case "focus":
                return "#0A6CFF"
            case "disabled":
                return "#c9c9c9"
            default:
                return "#e0e0e1"
        }
    }, [finalStatus])

    const BackgroundColor = useMemo(() => {
        switch (finalStatus) {
            case "valid":
                return "#e0ffe0"
            case "error":
                return "#ffe0e0"
            case "focus":
                return "#e6f0ff"
            case "disabled":
                return "#f0f0f0"
            default:
                return "#ffffff"
        }
    }, [finalStatus])

    const TextColor = useMemo(() => {
        if (!finalValue) {
            return "#c9c9c9"
        }
        switch (finalStatus) {
            case "valid":
                return "#008000"
            case "error":
                return "#ffadad"
            case "focus":
                return "#96c0ff"
            case "disabled":
                return "#c9c9c9"
            default:
                return "#000000"
        }
    }, [finalStatus, finalValue])

    const handleClick = useCallback(() => {
        if (disabled) {
            return
        }
        openModal(
            <ModalSelection
                value={finalValue as V}
                options={finalOptions as Option<V>[]}
                label={_label}
                onConfirm={(value) => {
                    onChange(value)
                    closeModal()
                }}
                onCancel={() => {
                    closeModal()
                }}
            />,
            selectionId,
        )
    }, [_label, closeModal, disabled, finalOptions, finalValue, onChange, openModal, selectionId])

    const finalIsModalOpen = useMemo(() => {
        return modalState.isOpen && selectionId === modalState.options?.activeId
    }, [modalState.isOpen, selectionId, modalState.options?.activeId])

    return (
        <div
            onClick={handleClick}
            css={css`
                flex: 1;
                position: relative;
                display: flex;
                flex-direction: row;
                align-items: center;
                justify-content: flex-start;
                font-family: "Gilroy", sans-serif;
                transition:
                    box-shadow 0.2s ease-in-out,
                    background-color 0.2s ease-in-out;
                flex: 1;
                min-height: 40rem;
                border: 1px solid #e0e0e0;
                border-radius: 8rem;
                padding: 0 16rem;
                box-shadow: inset 0 0 0 1.5rem ${BoxShadowColor};
                background-color: ${BackgroundColor};
                cursor: pointer;
                > * {
                    user-select: none;
                    pointer-events: none;
                }
                ${disabled ? "cursor: not-allowed;" : ""}
            `}
        >
            <div
                css={css`
                    display: flex;
                    align-items: center;
                    justify-content: flex-start;
                    flex: 1;
                    /* text */
                    font-weight: 500;
                    font-size: 16rem;
                    line-height: 24rem;
                    letter-spacing: 0%;
                    color: ${TextColor};
                `}
            >
                {finalDisplayValue as React.ReactNode}
            </div>
            <Svg
                src="base_image/arrow_down.svg"
                css={css`
                    transition: transform 0.2s ease-in-out;
                    width: 24rem;
                    height: 24rem;
                    transform: rotate(${finalIsModalOpen ? "180deg" : "0deg"});
                    * {
                        fill: ${TextColor};
                    }
                `}
            />
        </div>
    )
}

function ModalSelection<V>(props: {
    options: Option<V>[]
    onSelect?: (value: V) => void
    value: V
    label?: string
    onConfirm?: (value: V) => void
    onCancel?: () => void
}) {
    const [value, setValue] = useState<V>(props.value)
    const scrollContainerRef = useRef<HTMLDivElement>(null)

    useEffect(() => {
        props.onSelect?.(value)
    }, [props, value])

    const timeoutRef = useRef<NodeJS.Timeout | null>(null)

    const scrollToSelectedPosition = useCallback(
        (timeout: number = 200) => {
            if (!scrollContainerRef.current) return
            timeoutRef.current && clearTimeout(timeoutRef.current)
            // 找到當前值在選項中的索引
            const selectedIndex = props.options.findIndex((option) => option.value === value)

            if (selectedIndex >= 0) {
                const itemHeight = getCurrentPx(48)
                const scrollTop = selectedIndex * itemHeight
                // 延遲一小段時間後滾動，確保組件已完全渲染
                timeoutRef.current = setTimeout(() => {
                    scrollContainerRef.current?.scrollTo({
                        top: scrollTop,
                        behavior: "smooth",
                    })
                }, timeout)
            }
        },
        [props.options, value],
    )

    // 初始化滾動到選中值的位置
    useEffect(() => {
        scrollToSelectedPosition(50)
    }, [scrollToSelectedPosition])

    const handleCancel = useCallback(() => {
        props.onCancel?.()
    }, [props])

    const handleConfirm = useCallback(() => {
        props.onConfirm?.(value)
    }, [value, props])

    const handleScroll = useCallback(
        (event: React.UIEvent<HTMLDivElement>) => {
            window.requestAnimationFrame(() => {
                const target = event.target as HTMLDivElement
                const scrollTop = target.scrollTop
                const itemHeight = getCurrentPx(48)
                const centerIndex = Math.round(scrollTop / itemHeight)
                if (props.options[centerIndex]) {
                    setValue(props.options[centerIndex].value)
                    scrollToSelectedPosition()
                }
            })
        },
        [props.options, scrollToSelectedPosition],
    )

    return (
        <div
            css={css`
                display: flex;
                flex-direction: column;
                align-items: stretch;
                justify-content: flex-start;
                max-height: 320rem;
                border-radius: 8rem 8rem 0 0;
                overflow: hidden;
                font-family: "Gilroy", sans-serif;
            `}
        >
            <div
                css={css`
                    display: flex;
                    flex-direction: row;
                    align-items: center;
                    justify-content: space-between;
                    padding: 14rem 16rem;
                    /* 下方 shadow */
                    background-color: #ffffff;
                    border-bottom: 2rem solid #d1d1d1;
                `}
            >
                <div
                    onClick={handleCancel}
                    css={css`
                        font-family: Gilroy;
                        font-weight: 700;
                        font-size: 16rem;
                        line-height: 24rem;
                        letter-spacing: 0%;
                        text-align: center;
                        text-transform: capitalize;
                        color: #ff356b;
                        cursor: pointer;
                    `}
                >
                    Cancel
                </div>
                <div
                    css={css`
                        font-family: Gilroy;
                        font-weight: 700;
                        font-size: 16rem;
                        line-height: 24rem;
                        letter-spacing: 0%;
                        text-align: center;
                        text-transform: capitalize;
                        user-select: none;
                    `}
                >
                    {props.label ?? "Select"}
                </div>
                <div
                    onClick={handleConfirm}
                    css={css`
                        font-family: Gilroy;
                        font-weight: 700;
                        font-size: 16rem;
                        line-height: 24rem;
                        letter-spacing: 0%;
                        text-align: center;
                        text-transform: capitalize;
                        color: #ff356b;
                        cursor: pointer;
                    `}
                >
                    Confirm
                </div>
            </div>
            <div
                css={css`
                    position: relative;
                    display: flex;
                    flex-direction: column;
                    align-items: stretch;
                    justify-content: flex-start;
                    height: 280rem;
                    background-color: #ffffff;
                    &::after {
                        content: "";
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        right: 0;
                        top: 0;
                        z-index: 1;
                        user-select: none;
                        pointer-events: none;

                        background: linear-gradient(
                            to bottom,
                            #ffffff 0%,
                            #ffffff70 40%,
                            rgba(255, 255, 255, 0) 50%,
                            #ffffff70 60%,
                            #ffffff 100%
                        );
                    }
                `}
            >
                <Cursor />
                <div
                    ref={scrollContainerRef}
                    onScroll={handleScroll}
                    css={css`
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        right: 0;
                        top: 0;
                        padding: calc(50% - 78rem) 0;
                        overflow-y: scroll;
                        scroll-behavior: smooth;
                        ${hideScrollbarCss}
                    `}
                >
                    {props.options.map((option) => {
                        return (
                            <div
                                css={css`
                                    min-height: 48rem;
                                    display: flex;
                                    align-items: center;
                                    justify-content: center;

                                    /* text */
                                    font-weight: 600;
                                    font-size: 16rem;
                                    line-height: 22rem;
                                    letter-spacing: 0%;
                                    text-align: center;
                                `}
                            >
                                {option.label}
                            </div>
                        )
                    })}
                </div>
            </div>
        </div>
    )
}

const Cursor = styled.div`
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    user-select: none;
    pointer-events: none;
    height: 48rem;
    border-width: 1rem 0 1rem 0;
    border-style: solid;
    border-color: #d6d6d6;
`
